//author Sylvain Bertrand <digital.ragnarok@gmail.com>
//Protected by GNU Affero GPL v3 with some exceptions.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <error.h>

#include <linux/types.h>

#include <alga/pixel_fmts.h>
#include <alga/amd/dce6/dce6.h>
#include <alga/amd/si/ioctl.h>

#define e(m,...) error(0,0,m,##__VA_ARGS__)
#define unsignedl unsigned long

int main(int argc, char *argv[])
{
  if(argc<3){
    e("missing argument\n");
    goto err;
  }

  uint64_t fb_gpu_addr=strtoul(argv[2],NULL,16);

  int f=open("/dev/si0", O_RDWR);
  if(f==-1){
    e("open failed\n");
    goto err;
  }

  uint8_t i=(uint8_t)strtoul(argv[1],NULL,10);
  unsignedl req=_IOW('d',SI_DCE_DP_DPM,i);
  int r=ioctl(f,req,&i);
  if(r==-1){
    e("dp dpm failed\n");
    goto err_file_close;
  }

  req=_IOW('d',SI_MEM_FREE,fb_gpu_addr);
  r=ioctl(f,req,&fb_gpu_addr);
  if(r==-1){
    e("free vram fb failed (LEAK!)\n");
    goto err_file_close;
  }

  r=close(f);
  if(r==-1){
    e("close failed\n");
    goto err;
  }
  return 0;

err_file_close:
  r=close(f);
  if(r==-1) e("close failed\n");

err:
  return EXIT_FAILURE;
}
